/*
 * Copyright (C) 2013 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.picasso;

import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import okio.Source;

import java.io.IOException;

import static com.squareup.picasso.Utils.checkNotNull;

public abstract class RequestHandler {

    /**
     * Create bitmap options image source . decoding options.
     *
     * @param data the data
     * @return the image source . decoding options
     */
    public static ImageSource.DecodingOptions createBitmapOptions(Request data) {
        final boolean justBounds = data.hasSize();
        final boolean hasConfig = data.pixelFormat != null;
        ImageSource.DecodingOptions options = null;
        if (justBounds || hasConfig || data.purgeable) {
            options = new ImageSource.DecodingOptions();
            options.allowPartialImage= justBounds;
            if (hasConfig) {
                options.desiredPixelFormat = data.pixelFormat;
            }
        }
        return options;
    }

    /**
     * Requires in sample size boolean.
     *
     * @param options the Image source decoding options
     * @return the boolean value
     */
    static boolean requiresInSampleSize(ImageSource.DecodingOptions options) {
        return options != null && options.allowPartialImage;
    }

    /**
     * Calculate in sample size.
     *
     * @param targetWidth  the target width
     * @param targetHeight the target height
     * @param options      the options
     * @param request      the request data
     */
    public static void calculateInSampleSize(int targetWidth, int targetHeight, ImageSource.DecodingOptions options, Request request) {
        int width=options.desiredSize.width;
        int height=options.desiredSize.height;
    }

    /**
     * {@link Result} represents the result of a {@link #load(Request, int)} call in a
     * {@link RequestHandler}.
     *
     * @see RequestHandler
     * @see #load(Request, int) #load(Request, int)
     */
    public static final class Result {
        private final Picasso.LoadedFrom loadedFrom;
        private final PixelMap bitmap;
        private final Source source;
        private final int exifOrientation;

        /**
         * Instantiates a new Result.
         *
         * @param bitmap     the bitmap
         * @param loadedFrom the loaded from
         */
        public Result( PixelMap bitmap, Picasso.LoadedFrom loadedFrom) {
            this(checkNotNull(bitmap, "bitmap == null"), null, loadedFrom, 0);
        }

        /**
         * Instantiates a new Result.
         *
         * @param source     the source
         * @param loadedFrom the loaded from
         */
        public Result(Source source, Picasso.LoadedFrom loadedFrom) {
            this(null, checkNotNull(source, "source == null"), loadedFrom, 0);
        }

        /**
         * Instantiates a new Result.
         *
         * @param bitmap          the bitmap
         * @param source          the source
         * @param loadedFrom      the loaded from
         * @param exifOrientation the exif orientation
         */
        Result(
                PixelMap bitmap,
                 Source source,
                 Picasso.LoadedFrom loadedFrom,
                int exifOrientation) {
            if ((bitmap != null) == (source != null)) {
                throw new AssertionError();
            }
            this.bitmap = bitmap;
            this.source = source;
            this.loadedFrom = checkNotNull(loadedFrom, "loadedFrom == null");
            this.exifOrientation = exifOrientation;
        }

        /**
         * The loaded { Bitmap}. Mutually exclusive with {@link #getSource()}.
         * @return the bitmap
         */
        public PixelMap getBitmap() {
            return bitmap;
        }

        /**
         * A stream of image data. Mutually exclusive with {@link #getBitmap()}.
         * @return the source
         */
        public Source getSource() {
            return source;
        }

        /**
         * Returns the resulting {@link Picasso.LoadedFrom} generated from a
         * {@link #load(Request, int)} call.
         *
         * @return the loaded from
         */
        public Picasso.LoadedFrom getLoadedFrom() {
            return loadedFrom;
        }

        /**
         * Returns the resulting EXIF orientation generated from a {@link #load(Request, int)} call.
         * This is only accessible to built-in RequestHandlers.
         *
         * @return the exif orientation
         */
        int getExifOrientation() {
            return exifOrientation;
        }
    }

    /**
     * Whether or not this {@link RequestHandler} can handle a request with the given {@link Request}.
     *
     * @param data request data
     * @return the boolean value
     */
    public abstract boolean canHandleRequest(Request data);

    /**
     * Loads an image for the given {@link Request}.
     *
     * @param request the data from which the image should be resolved.
     * @param networkPolicy the {NetworkPolicy} for this request.
     * @return the result
     * @throws IOException                the io exception
     * @throws DataAbilityRemoteException the data ability remote exception
     */
    public abstract Result load(Request request, int networkPolicy) throws IOException, DataAbilityRemoteException;

    /**
     * Gets retry count.
     *
     * @return the retry count
     */
    int getRetryCount() {
        return 0;
    }

    /**
     * Should retry boolean.
     *
     * @param airplaneMode the airplane mode
     * @return the boolean
     */
    boolean shouldRetry(boolean airplaneMode) {
        return false;
    }

    /**
     * Supports replay boolean.
     *
     * @return the boolean
     */
    boolean supportsReplay() {
        return false;
    }
}
